package com.dongframe.demo.utils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * String Utils
 * 
 */
public class StringUtils
{
    
    private StringUtils()
    {
        throw new AssertionError();
    }
    
    /**
     * is null or its length is 0 or it is made by space 判断字符串是否为空或长度为0 或由空格组成
     * 
     * <pre>
     * isBlank(null) = true;
     * isBlank(&quot;&quot;) = true;
     * isBlank(&quot;  &quot;) = true;
     * isBlank(&quot;a&quot;) = false;
     * isBlank(&quot;a &quot;) = false;
     * isBlank(&quot; a&quot;) = false;
     * isBlank(&quot;a b&quot;) = false;
     * </pre>
     * 
     * @param str
     * @return if string is null or its size is 0 or it is made by space, return
     *         true, else return false.
     */
    public static boolean isBlank(String str)
    {
        return (str == null || str.trim().length() == 0);
    }
    
    /**
     * is null or its length is 0 判断字符串是否为空或长度为0
     * 
     * <pre>
     * isEmpty(null) = true;
     * isEmpty(&quot;&quot;) = true;
     * isEmpty(&quot;  &quot;) = false;
     * </pre>
     * 
     * @param str
     * @return if string is null or its size is 0, return true, else return
     *         false.
     */
    public static boolean isEmpty(CharSequence str)
    {
        return (str == null || str.length() == 0 || null == str || "null".equals(str));
    }
    
    /**
     * 判断是否为null
     * @param str
     * @return
     */
    public static boolean isNullEmpty(CharSequence str)
    {
        return str == null;
    }
    
    /**
     * compare two string 
     * 
     * @param actual
     * @param expected
     * @return
     * @see ObjectUtils#isEquals(Object, Object)
     */
    public static boolean isEquals(String actual, String expected)
    {
        return ObjectUtils.isEquals(actual, expected);
    }
    
    /**
     * get length of CharSequence 
     * 
     * <pre>
     * length(null) = 0;
     * length(\"\") = 0;
     * length(\"abc\") = 3;
     * </pre>
     * 
     * @param str
     * @return if str is null or empty, return 0, else return
     *         {@link CharSequence#length()}.
     */
    public static int length(CharSequence str)
    {
        return str == null ? 0 : str.length();
    }
    
    /**
     * null Object to empty string
     * 
     * <pre>
     * nullStrToEmpty(null) = &quot;&quot;;
     * nullStrToEmpty(&quot;&quot;) = &quot;&quot;;
     * nullStrToEmpty(&quot;aa&quot;) = &quot;aa&quot;;
     * </pre>
     * 
     * @param str
     * @return
     */
    public static String nullStrToEmpty(Object str)
    {
        return (str == null ? "" : (str instanceof String ? (String)str : str.toString()));
    }
    
    /**
     * capitalize first letter 首字母大写
     * 
     * <pre>
     * capitalizeFirstLetter(null)     =   null;
     * capitalizeFirstLetter("")       =   "";
     * capitalizeFirstLetter("2ab")    =   "2ab"
     * capitalizeFirstLetter("a")      =   "A"
     * capitalizeFirstLetter("ab")     =   "Ab"
     * capitalizeFirstLetter("Abc")    =   "Abc"
     * </pre>
     * 
     * @param str
     * @return
     */
    public static String capitalizeFirstLetter(String str)
    {
        if (isEmpty(str))
        {
            return str;
        }
        
        char c = str.charAt(0);
        return (!Character.isLetter(c) || Character.isUpperCase(c)) ? str
            : new StringBuilder(str.length()).append(Character.toUpperCase(c)).append(str.substring(1)).toString();
    }
    
    /**
     * encoded in utf-8 以utf-8格式编码
     * 
     * <pre>
     * utf8Encode(null)        =   null
     * utf8Encode("")          =   "";
     * utf8Encode("aa")        =   "aa";
     * utf8Encode("啊啊啊啊")   = "%E5%95%8A%E5%95%8A%E5%95%8A%E5%95%8A";
     * </pre>
     * 
     * @param str
     * @return
     * @throws UnsupportedEncodingException
     *             if an error occurs
     */
    public static String utf8Encode(String str)
    {
        if (!isEmpty(str) && str.getBytes().length != str.length())
        {
            try
            {
                return URLEncoder.encode(str, "UTF-8");
            }
            catch (UnsupportedEncodingException e)
            {
                throw new RuntimeException("UnsupportedEncodingException occurred. ", e);
            }
        }
        return str;
    }
    
    /**
     * encoded in utf-8, if exception, return defultReturn
     * 
     * @param str
     * @param defultReturn
     * @return
     */
    public static String utf8Encode(String str, String defultReturn)
    {
        if (!isEmpty(str) && str.getBytes().length != str.length())
        {
            try
            {
                return URLEncoder.encode(str, "UTF-8");
            }
            catch (UnsupportedEncodingException e)
            {
                return defultReturn;
            }
        }
        return str;
    }
    
    /**
     * get innerHtml from href
     * 
     * <pre>
     * getHrefInnerHtml(null)                                  = ""
     * getHrefInnerHtml("")                                    = ""
     * getHrefInnerHtml("mp3")                                 = "mp3";
     * getHrefInnerHtml("&lt;a innerHtml&lt;/a&gt;")                    = "&lt;a innerHtml&lt;/a&gt;";
     * getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
     * getHrefInnerHtml("&lt;a&lt;a&gt;innerHtml&lt;/a&gt;")                    = "innerHtml";
     * getHrefInnerHtml("&lt;a href="baidu.com"&gt;innerHtml&lt;/a&gt;")               = "innerHtml";
     * getHrefInnerHtml("&lt;a href="baidu.com" title="baidu"&gt;innerHtml&lt;/a&gt;") = "innerHtml";
     * getHrefInnerHtml("   &lt;a&gt;innerHtml&lt;/a&gt;  ")                           = "innerHtml";
     * getHrefInnerHtml("&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                      = "innerHtml";
     * getHrefInnerHtml("jack&lt;a&gt;innerHtml&lt;/a&gt;&lt;/a&gt;")                  = "innerHtml";
     * getHrefInnerHtml("&lt;a&gt;innerHtml1&lt;/a&gt;&lt;a&gt;innerHtml2&lt;/a&gt;")        = "innerHtml2";
     * </pre>
     * 
     * @param href
     * @return <ul>
     *         <li>if href is null, return ""</li>
     *         <li>if not match regx, return source</li>
     *         <li>return the last string that match regx</li>
     *         </ul>
     */
    public static String getHrefInnerHtml(String href)
    {
        if (isEmpty(href))
        {
            return "";
        }
        
        String hrefReg = ".*<[\\s]*a[\\s]*.*>(.+?)<[\\s]*/a[\\s]*>.*";
        Pattern hrefPattern = Pattern.compile(hrefReg, Pattern.CASE_INSENSITIVE);
        Matcher hrefMatcher = hrefPattern.matcher(href);
        if (hrefMatcher.matches())
        {
            return hrefMatcher.group(1);
        }
        return href;
    }
    
    /**
         * process special char in html
         * 
         * <pre>
         * htmlEscapeCharsToString(null) = null;
         * htmlEscapeCharsToString("") = "";
         * htmlEscapeCharsToString("mp3") = "mp3";
         * htmlEscapeCharsToString("mp3&lt;") = "mp3<";
         * htmlEscapeCharsToString("mp3&gt;") = "mp3\>";
         * htmlEscapeCharsToString("mp3&amp;mp4") = "mp3&mp4";
         * htmlEscapeCharsToString("mp3&quot;mp4") = "mp3\"mp4";
         * htmlEscapeCharsToString("mp3&lt;&gt;&amp;&quot;mp4") = "mp3\<\>&\"mp4";
         * </pre>
         * 
         * @param source
         * @return
         */
    public static String htmlEscapeCharsToString(String source)
    {
        return StringUtils.isEmpty(source) ? source
            : source.replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&amp;", "&").replaceAll("&quot;",
                "\"");
    }
    
    /**
     * transform half width char to full width char
     * 
     * <pre>
     * fullWidthToHalfWidth(null) = null;
     * fullWidthToHalfWidth("") = "";
     * fullWidthToHalfWidth(new String(new char[] {12288})) = " ";
     * fullWidthToHalfWidth("！＂＃＄％＆) = "!\"#$%&";
     * </pre>
     * 
     * @param s
     * @return
     */
    public static String fullWidthToHalfWidth(String s)
    {
        if (isEmpty(s))
        {
            return s;
        }
        
        char[] source = s.toCharArray();
        for (int i = 0; i < source.length; i++)
        {
            if (source[i] == 12288)
            {
                source[i] = ' ';
                // } else if (source[i] == 12290) {
                // source[i] = '.';
            }
            else if (source[i] >= 65281 && source[i] <= 65374)
            {
                source[i] = (char)(source[i] - 65248);
            }
            else
            {
                source[i] = source[i];
            }
        }
        return new String(source);
    }
    
    /**
     * transform full width char to half width char
     * 
     * <pre>
     * halfWidthToFullWidth(null) = null;
     * halfWidthToFullWidth("") = "";
     * halfWidthToFullWidth(" ") = new String(new char[] {12288});
     * halfWidthToFullWidth("!\"#$%&) = "！＂＃＄％＆";
     * </pre>
     * 
     * @param s
     * @return
     */
    public static String halfWidthToFullWidth(String s)
    {
        if (isEmpty(s))
        {
            return s;
        }
        
        char[] source = s.toCharArray();
        for (int i = 0; i < source.length; i++)
        {
            if (source[i] == ' ')
            {
                source[i] = (char)12288;
                // } else if (source[i] == '.') {
                // source[i] = (char)12290;
            }
            else if (source[i] >= 33 && source[i] <= 126)
            {
                source[i] = (char)(source[i] + 65248);
            }
            else
            {
                source[i] = source[i];
            }
        }
        return new String(source);
    }
    
    /**
     * 小于10  前面补个0  
     * @return
     */
    public static String completion(int str)
    {
        if (str < 10)
        {
            return "0" + str;
        }
        
        return str + "";
        
    }
    
    /**
     * 小于10  前面补个0  
     * @return
     */
    public static String completion(String str)
    {
        if (Integer.valueOf(str) < 10)
        {
            return "0" + str;
        }
        
        return str;
        
    }
}
